<?php

namespace Mini;

class ConcurrencyLimiter
{
    protected int $limit;
    protected int $running = 0;
    protected array $queue = [];

    public function __construct(int $limit)
    {
        $this->limit = $limit;
    }

    public function run(callable $task): void
    {
        if ($this->running < $this->limit) {
            $this->startTask($task);
        } else {
            $this->queue[] = $task;
        }
    }

    protected function startTask(callable $task): void
    {
        $this->running++;
        App::loop()->add(function () use ($task) {
            try {
                $task();
            } finally {
                $this->running--;
                if (!empty($this->queue)) {
                    $next = array_shift($this->queue);
                    $this->startTask($next);
                }
            }
        });
    }
}
